import asyncio
import json

import aioredis
from datetime import datetime

class RedisHelper:
    def __init__(self):
        self.redis_pool = None

    async def connect(self):
        # 创建连接池（建议设置合理的 max_connections）
        self.redis_pool = await aioredis.from_url(
            "redis://192.168.141.15:6379/1",
            decode_responses=True,
            max_connections=1000,# 根据服务器配置调整
            socket_keepalive=True  # 保持长连接

        )

    async def disconnect(self):
        if self.redis_pool:
            await self.redis_pool.close()

    async def get_cache(self, key):
        """
        获取缓存。
        从 Redis 获取值并反序列化为字典或列表。
        如果数据不是有效的 JSON 格式，则返回 None。
        """
        # 从 Redis 获取值，可能是 bytes 或 str 类型
        value = await self.redis_pool.get(key)

        if value is None:  # 如果键不存在，直接返回 None
            return None

        # 确保 value 是字符串类型
        try:
            if isinstance(value, bytes):
                value_str = value.decode('utf-8')  # 解码字节为字符串
            elif isinstance(value, str):
                value_str = value  # 如果已经是字符串，直接使用
            else:
                return None  # 如果数据类型不支持，返回 None
        except UnicodeDecodeError:
            # 如果解码失败，说明数据不是 UTF-8 编码
            return None  # 或者返回原始的 bytes 数据，视需求而定

        # 尝试将字符串反序列化为 JSON 对象
        try:
            return json.loads(value_str)  # 反序列化为字典或列表
        except json.JSONDecodeError:
            # 如果不是合法的 JSON 格式，返回 None
            return None

    async def set_cache(self, key, value, timeout=None):
        """
        设置缓存。
        根据值的类型选择存储方式：
        - 字典或列表：序列化为 JSON 字符串后存储。
        - 数字、字符串、布尔值：直接存储为字符串。
        """
        if isinstance(value, (dict, list)):
            # 如果是字典或列表，序列化为 JSON 字符串
            serialized_value = json.dumps(value)
        elif isinstance(value, (int, float, str, bool)):
            # 如果是数字、字符串或布尔值，直接转换为字符串
            serialized_value = str(value)
        else:
            raise ValueError("Unsupported data type. Value must be a dictionary, list, number, string, or boolean.")

        # 存储到 Redis，并设置过期时间
        await self.redis_pool.set(key, serialized_value, ex=timeout)

    async def decrement_stock(self, key):
        # 扣减库存
        lua_script = """
        local stock_key = KEYS[1]
        local current_stock = tonumber(redis.call("GET", stock_key))
        if current_stock and current_stock > 0 then
            redis.call("DECR", stock_key)
            return current_stock - 1
        else
            return -1
        end
        """
        return await self.redis_pool.eval(lua_script, 1, key)